home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / pclcjs.arj / GLBL_ENV.C < prev    next >
Text File  |  1993-01-03  |  10KB  |  333 lines

  1. /* I have adapted Clay Davis' modification of Peter Thomas' adaptation
  2.    of David Dubois' BASIC routines found on CompuServe. (whew!)  Believe
  3.    it or not, the Microsoft C version compiled and ran WITHOUT ERROR
  4.    and WITHOUT MODIFICATION under Power C 2.2.0.  I have included these
  5.    functions in my CJSLIB function library, and am indebted to the above
  6.    mentioned individuals for their willingness to share their techniques.  
  7.    
  8.    Chuck Steenburgh [72330,1776]                                           */
  9.  
  10. /*****************************************************************************
  11.    This is a version of GLBL.ARC which was slightly modified to be used
  12.    in Microsoft-C.  The following changes were made:
  13.  
  14.    1.  All calls to _farmalloc were replaced with _fmalloc
  15.    2.  All calls to _farfree were replaced with _ffree
  16.    3.  MS-C does not have an _mk_fp function which converts a pointer to
  17.        a far pointer.  So, this task was done by multiplying the segment by
  18.        0x10000 to shift the pointer.
  19.  
  20.    Other than these changes (Isn't C portable), the routine runs as stated
  21.    in the MS-C medium model.  Other models should work also.
  22.  
  23.    Modified by Clay Davis 76346,101 on July 11, 1988.  Tested using MS-C 5.1.
  24.  
  25.    ************************************************************************
  26.  
  27.    This code is based upon the program SETPATH.PAS (located in BPROGA) by
  28.    David Dubois [71401,747]
  29.  
  30.    This Turbo C version is written by Peter Thomas [75716,2377]
  31.  
  32.    This series of routines are designed to Locate, Retrieve, Update, and
  33.    Remove "Variables" from the MASTER copy of the DOS Environment table.
  34.    The routines have been written in a manner that avoids linking any
  35.    EXTERNAL routines for string manipulation, and thus should be independent
  36.    of memory model being used.
  37.  
  38.    Be careful that changes made to the Environment with these routines
  39.    ONLY OCCUR IN THE MASTER COPY, and that if COMMAND.COM is spawned
  40.    from a routine that has changed the environment, NO CHANGES WILL BE
  41.    SEEN IN THE ENVIRONMENT. This is most apparent when this program is run
  42.    in the INTEGRATED environment: changes made by this technique will
  43.    not appear if the "OS Shell" is invoked, and will only appear on exit
  44.    from TC.
  45.  
  46.    For full documentation on the techniques used here can be found in the
  47.    file COMENV.ARC located in LIB 2 of BPROGA on Compuserve.
  48.  
  49.    As David Dubois says:
  50.  
  51.   I hereby dedicate this knowledge to the public domain. Feel free to use
  52.   it, but if you do, please mention my name. There are no guarantees, and
  53.   in fact, I wouldn't bet a dollar that it will work every time.
  54.  
  55.   That this works at all is based on experimental, rather than properly
  56.   documented, evidence. There are no guarantees. But then, its free.
  57.  
  58. *****************************************************************************/
  59.  
  60. #include <dos.h>
  61. #include <stdio.h> /* MS-C requires this */
  62. #include <stdlib.h> /* MS-C requires this */
  63. #include <malloc.h> /* MS-C uses this instead of alloc.h */
  64.  
  65. /*
  66.  *   Mstr_FindEnvironment:
  67.  *     Scans for the "Master" Environment area, and returns
  68.  *     a pointer to it, and the size of the environment.
  69. */
  70.  
  71. void Mstr_FindEnvironment ( char far **Env , unsigned *EnvSize )
  72. {
  73.    unsigned int far *CommandSeg, far *TempSeg ;
  74.    char far *BlockSeg ;
  75.  
  76.    /*
  77.     *  Scan through PSP's looking for a block that is its own father.
  78.     *  This block is the PSP of COMMAND.COM
  79.    */
  80.   TempSeg = _psp*0x10000; /* Convert to a far pointer, replaces MK_FP */
  81.    do
  82.    {
  83.      CommandSeg = TempSeg ;
  84.      TempSeg = *(TempSeg+8)*0x10000; /* Replaces MK_FP in turbo C */
  85.    }
  86.    while ( TempSeg != CommandSeg ) ;
  87.  
  88.    /*
  89.     *  Scan forward through memory looking for the correct MSB.
  90.     *  This will have COMMAND.COM's PSP as owner, and begin with
  91.     *  the character M
  92.    */
  93.    BlockSeg = (char far *)CommandSeg ;
  94.    do
  95.    {
  96.     BlockSeg = (FP_SEG(BlockSeg)+1)*0x10000; /* Replaces MK_FP */
  97.    }
  98.    while ( ( *(unsigned int far *)(BlockSeg+1) != FP_SEG ( CommandSeg ) ) ||
  99.            ( *BlockSeg != 'M' ) ) ;
  100.  
  101.    /*
  102.     *  The environment is the NEXT segment of memory
  103.     *  and bytes 4 and 5 are the size in paragraphs
  104.    */
  105.    *Env = (FP_SEG(BlockSeg)+1)*0x10000; /* Replaces MK_FP */
  106.    *EnvSize = 16 * *(unsigned int far *)(BlockSeg+3) ;
  107. }
  108.  
  109.  
  110.  
  111.  
  112. /*
  113.  *   Mstr_getenv:
  114.  *     Scans the "Master" Environment for a given "sub string"
  115.  *     and returns a pointer to it.
  116.  *     Similar to Turbo routine "getenv" but uses the Master copy of the
  117.  *     environment table.
  118. */
  119.  
  120. char far *Mstr_getenv (char far *Env , char far *name)
  121. {
  122.    char far *Sub_Env, far *str1, far *str2 ;
  123.  
  124.    /*
  125.     *  Start at the beginning of the environment
  126.    */
  127.    Sub_Env = Env ;
  128.  
  129.    /*
  130.     *  While the "sub string" we're looking at is non-zero
  131.    */
  132.    for ( ; *Sub_Env ; )
  133.    {
  134.      /*
  135.       *  Simulate a "strcmp" on the "sub string" of the environment
  136.       *  and the string we're looking for
  137.      */
  138.      for ( str1 = Sub_Env , str2 = name ;
  139.            (*str1) && (*str2) && ( *str1 == *str2) ;
  140.            str1++ , str2++ ) ;
  141.      /*
  142.       *  If we reached the end of the string we're looing for
  143.       *  we've found the correct portion of the environment.
  144.       *  Return the ptr to the start of this "sub string"
  145.      */
  146.      if ( !*str2 )
  147.        return ( Sub_Env ) ;
  148.  
  149.      /*
  150.       *  Otherwise, advance to the next "sub string" in the environment
  151.       *  by performing a "strchr" function
  152.      */
  153.      for ( ; *(Sub_Env++) ; ) ;
  154.    }
  155.  
  156.    /*
  157.     *  Obviously, the string is not present in the environment.
  158.     *  Return this fact.
  159.    */
  160.   return ( NULL ) ;
  161. }
  162.  
  163.  
  164.  
  165.  
  166. /*
  167.  *   Mstr_delenv:
  168.  *     Scans the "Master" Environment for a given "sub string"
  169.  *     and removes it.
  170. */
  171.  
  172. int Mstr_delenv (char far *Env , unsigned EnvSize , char far *name)
  173. {
  174.    char far *Sub_Env , far *New_Env ;
  175.    char huge *Dest , far *Src , huge *End_Env ;
  176.  
  177.    int Done  ;
  178.    unsigned Ctr ;
  179.  
  180.    /*
  181.     *  Allocate a chunk of storage to act as a "working" copy of
  182.     *  the Environment table
  183.    */
  184.    New_Env = _fmalloc ( EnvSize ) ;
  185.  
  186.    /*
  187.     *  Copy the data from the Master to Working copy of the
  188.     *  Environment table.
  189.     *  Simulates a "memcpy" function.
  190.    */
  191.    for ( Src = Env , Dest = (char far *)New_Env , Ctr = 0 ;
  192.          Ctr < EnvSize ;
  193.          *(Dest++) = *(Src++) , Ctr++ ) ;
  194.  
  195.    /*
  196.     *  Scan the working copy of the environment for the desired
  197.     *  sub string
  198.    */
  199.    Sub_Env = Mstr_getenv ( New_Env , name ) ;
  200.  
  201.    if ( Sub_Env == NULL )
  202.    {
  203.      /*
  204.       *  If not found, do nothing
  205.      */
  206.      Done = -1 ;
  207.    } else {
  208.      /*
  209.       *  Locate the end of the string to delete
  210.       *  Simulate a "strchr" call
  211.      */
  212.      for ( Src = Sub_Env ; *(Src++) ; ) ;
  213.  
  214.      /*
  215.       *  Move the rest of the environment back over the "sub string"
  216.       *  being deleted.
  217.       *  Simulated "memcpy" function.
  218.       *  Huge pointers used for pointer comparison purposes.
  219.      */
  220.      for ( Dest = (char huge *)Sub_Env , End_Env = (char huge *) (New_Env + EnvSize ) ;
  221.          ( Dest < End_Env ) ;
  222.          *(Dest++) = *(Src++) ) ;
  223.  
  224.      /*
  225.       *  Copy the data from the Working to Master copy of the
  226.       *  Environment table.
  227.       *  Simulates a "memcpy" function.
  228.      */
  229.      for ( Src = New_Env , Dest = (char huge *)Env , Ctr = 0 ;
  230.          Ctr < EnvSize ;
  231.          *(Dest++) = *(Src++) , Ctr++ ) ;
  232.  
  233.      /*
  234.       *  Signal all done
  235.      */
  236.      Done = 0 ;
  237.    }
  238.  
  239.    /*
  240.     *  Free all working storage
  241.    */
  242.    _ffree ( New_Env ) ;
  243.  
  244.    return ( Done ) ;
  245. }
  246.  
  247.  
  248.  
  249.  
  250. /*
  251.  *   Mstr_putenv:
  252.  *     Adds/Replaces a given "sub string" in the Master Environment.
  253.  *     Similar to Turbo routine "putenv" but uses the Master copy of the
  254.  *     environment table.
  255. */
  256.  
  257. int Mstr_putenv (char far *Env , unsigned EnvSize , char far *name )
  258. {
  259.    char far *Sub_Env , far *Temp_Name ;
  260.    char huge *Dest , far *Src , huge *End_Env ;
  261.    int Done ;
  262.  
  263.    /*
  264.     *  Allocate a chunk of storage to create the Variable name to add
  265.     *  to the Environment table
  266.    */
  267.    Temp_Name = _fmalloc ( 256 ) ;
  268.  
  269.    /*
  270.     *  Extract only the Name portion of the data to add to the Environment
  271.    */
  272.    for ( Src = name , Dest = Temp_Name ;
  273.          *Src && ( *Src != '=' ) ;
  274.         *(Dest++) = *(Src++) ) ;
  275.  
  276.    /*
  277.     *  Ensure that the resulting name is well formed.
  278.    */
  279.    *(Dest++) = '=' ;
  280.    *Dest = 0 ;
  281.  
  282.    /*
  283.     *  Delete this sub string if found in the environment
  284.    */
  285.    Mstr_delenv ( Env , EnvSize , Temp_Name ) ;
  286.  
  287.    /*
  288.     *  Locate the END of the Master table by locating a zero length
  289.     *  String in it
  290.    */
  291.    Sub_Env = Env ;
  292.    for ( ; *Sub_Env ; )
  293.    {
  294.      for ( ; *(Sub_Env++) ; ) ;
  295.    }
  296.  
  297.    /*
  298.     *  Add the new string to the END of the existing environment, with
  299.     *  trincation IF needed
  300.    */
  301.    for ( Dest = (char huge *)(Sub_Env) , Src = name , End_Env = (char huge *) (Env + EnvSize ) ;
  302.          ( Dest < End_Env ) && (*Src) ;
  303.          *(Dest++) = *(Src++) ) ;
  304.  
  305.    Done = -1 ;
  306.    if ( !*Src )
  307.    {
  308.      /*
  309.       *  If the string to add was FULLY added, ensure that the
  310.       *  newly updated environment is properly finished
  311.      */
  312.      Done = 0 ;
  313.      *(Dest++) = 0 ;
  314.      *Dest = 0 ;
  315.    }
  316.  
  317.    /*
  318.     *  As a real safety measure, ensure that the FINAL two bytes of the
  319.     *  Environment are both 0. This will finish the last string AND
  320.     *  ensure that a zero length string is also present
  321.    */
  322.    *(End_Env-1) = 0 ;
  323.   *(End_Env-2) = 0 ;
  324.  
  325.    /*
  326.     *  Free all working storage
  327.    */
  328.    _ffree ( Temp_Name ) ;
  329.  
  330.    return ( Done ) ;
  331. }
  332.  
  333.